package thread.pc;

public class Restaurant {

	Order order; // Package access

	public static void main(String[] args) {
		Restaurant restaurant = new Restaurant();
		WaitPerson sylar = new WaitPerson(restaurant,"Sylar 噶不瑞");
		WaitPerson peter = new WaitPerson(restaurant,"Peter 配踔厉");
		WaitPerson michael = new WaitPerson(restaurant,"Michael 史高飞");
		new Chef(restaurant);
	}
}

class Order { // 附带“倒数”终止程序作用
	private static int i = 0;

	private int count = i++;

	public Order() {
		if (count == 10) {
			System.out.println("Out of food, closing");
			System.exit(0);
		}
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "Order" + count;
	}
}

class WaitPerson extends Thread {
	private Restaurant restaurant;

	public WaitPerson(Restaurant restaurant, String name) {
		super(name);
		this.restaurant = restaurant;
		start();
	}

	@Override
	public void run() {
		while (true) {
			synchronized (restaurant) { // 自己改的，这样合理些，多个waiter抢order的时候不会出问题
				System.out.println(getName() + " 得到了锁");
				while (restaurant.order == null) {
					System.out.println(getName() + "发现厨师还没做好菜，开始等待");
					try {
						restaurant.wait();
						System.out.println(getName() + " 等待结束，并拿回锁");
					} catch (InterruptedException e) {
						throw new RuntimeException(e);
					}
				}
				System.out.println(getName()+" 抢到了盘子~ " + restaurant.order);
				System.out.println();
				restaurant.order = null;
			}	
		}
	}
}

class Chef extends Thread {
	private Restaurant restaurant;

	public Chef(Restaurant restaurant) {
		this.restaurant = restaurant;
		start();
	}

	public void run() {
		while (true) {
			if (restaurant.order == null) {
				restaurant.order = new Order();
				System.out.println("厨师做好了一盘菜！提醒大家来端！ ");
				//System.out.println("厨师做好了一盘菜！随便叫一个来端！ ");
				synchronized (restaurant) {
					restaurant.notifyAll(); 
					// restaurant.notify(); 
				}
			}
			
			try {
				sleep(200);
			} catch(InterruptedException e){
				throw new RuntimeException(e);
			}
		}
	}
}